/***********************************************************************************
 * 文件名： mcu_spi.c
 * 作者： 黄均铭
 * 版本： 1
 * 说明：
 * 		SPI驱动。
 * 修改记录：
 * 	2024年1月8日: 初版。 黄均铭。
 ***********************************************************************************/
#include "mcu.h"

#if (SPI_DIVN & 0x1) || (SPI_DIVN < 2)
#error "SPI_DIVN必须为大于1的偶数"
#endif

/////////////////////////////// 内部函数
// SPI发送接收函数
// static u8 Spi_TransByte(u8 dat);

// // SPI发送函数 - 不阻塞
// static void SPI_SendOnceAsync(u8 dat);

// // SPI发送函数 - 阻塞
// static void SPI_SendOnceSync(u8 dat);

// SPI初始化
// 不包含IO口初始化
void Spi_Init(void)
{
    /* 开启SSP模块时钟 */
    SYS_EnablePeripheralClk(SYS_CLK_SSP_MSK);

    // 初始化
    SSP->CLK = ((0xff & SPI_DIVM) << 8) | (0xff & SPI_DIVN);
    SSP->CON = (SPI_CPH << 7) | (SPI_CPO << 6) | (SPI_DSS - 1);
    SSP->CSCR = 0x04;

    // 启动SPI
    SSP->CON |= (SSP_CON_SSPEN_Msk);
}

// SPI发送函数 - 阻塞
bool Spi_SendSync(const u8* t_buff, size_t len)
{
    vu16 _d;
    while (len)
    {
        u8 opt_len = 8;
        if(opt_len > len)opt_len = len;
        while(!Spi_GetTFE());
        for(u8 i = 0; i < opt_len; i++)
        {
            SSP->DAT = *t_buff;
            t_buff++;
        }
        len -= opt_len;
    }
    // 等待空闲(1:正在发送/接收或者发送FIFO非空)
    while(Spi_GetBSY());
    // 判断接收FIFO非空（1：接收FIFO非空）
    while (Spi_GetRNE())
    {
        _d = SSP->DAT;
    }

    return true;
}

// SPI数据传送
bool Spi_Trans(u8* r_buff, const u8* t_buff, size_t len)
{
    if (r_buff == NULL && t_buff == NULL)
        return false;
    else if (r_buff == NULL)
        return Spi_SendSync(t_buff, len);
    else
    {
        // u16 i;
        // for (i = 0; i < len; i++)
        // {
        //     if (t_buff != NULL)
        //     {
        //         r_buff[i] = Spi_TransByte(t_buff[i]);
        //     }
        //     else
        //     {
        //         r_buff[i] = Spi_TransByte(0x00);
        //     }
        // }
        u8 i, opt_len;
        while(len)
        {
            // 发8个
            opt_len = 8;
            if(opt_len > len)opt_len = len;
            while(!Spi_GetTFE());
            for (i = 0; i < opt_len; i++)
            {
                SSP->DAT = *t_buff;
                t_buff++;
            }
            // 等待8个发完
            while(Spi_GetBSY());
            // 收8个
            while (Spi_GetRNE())
            {
                *r_buff = SSP->DAT;
                r_buff++;
            }
            // 等待并收8个
            // for(i = 0; i < opt_len; i++)
            // {
            //     while(!Spi_GetRNE());
            //     *r_buff = SSP->DAT;
            //     r_buff++;
            // }
            len -= opt_len;
        }
    }
    return true;
}

/////////////////////////////// 内部函数
// SPI发送接收函数，一个字节
// static u8 Spi_TransByte(u8 dat)
// {
//     // 等待空闲(1:正在发送/接收或者发送FIFO非空)
//     while (Spi_GetBSY())
//         ;
//     // // 等待发送FIFO为空
//     // while (!Spi_GetTFE())
//     //     ;
//     // // 等待发送FIFO未满
//     // while (!Spi_GetTNF())
//     //     ;
//     // 发送数据
//     SSP->DAT = dat;
//     // 等待接收FIFO非空
//     while (!Spi_GetRNE())
//         ;
//     // 返回读取数据
//     return (0xffff & (SSP->DAT));
// }

// // SPI发送函数 - 不阻塞
// static void SPI_SendOnceAsync(u8 dat)
// {
//     // 等待发送FIFO未满
//     while (!Spi_GetTNF())
//         ;
//     // 发送数据
//     SSP->DAT = dat;
// }

// // SPI发送函数 - 阻塞
// static void SPI_SendOnceSync(u8 dat)
// {
//     // 等待空闲(1:正在发送/接收或者发送FIFO非空)
//     while (Spi_GetBSY())
//         ;
//     // 发送数据
//     SSP->DAT = dat;

//     // 等待空闲(1:正在发送/接收或者发送FIFO非空)
//     while (Spi_GetBSY())
//         ;
// }
